﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace PhraseCorrector.Init
{
    /// <summary>
    /// 嵌入资源类，用于加载和保存各种资源文件。
    /// </summary>
    internal class EmbeddedResources
    {

        #region 专用静态变量
        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 根程序集，用于从中获取嵌入的资源。
        /// </summary>
        public static string[] codes;

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 拼音哈希表
        /// </summary>
        public static short[][] hashes;

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 繁体字到简体字的映射表，支持将繁体字转换为简体字。
        /// </summary>
        public static Dictionary<string, string> Q2b { get; set; }
        #endregion

        #region 私有变量

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 根类型，用于辅助定位资源的命名空间。
        /// </summary>
        private static Type RootType { get; }= typeof(PhraseCorrect);

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 资源前缀，用于构建资源的完整名称。
        /// </summary>
        private static string Prefix { get; }= $"{RootType.Namespace}.Dics";

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 获取当前程序集
        /// </summary>
        private static Assembly RootAssembly { get; }= typeof(EmbeddedResources).Assembly;

        #endregion

        #region 初始化
        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 读取嵌入资源类的构造函数
        /// </summary>
        public EmbeddedResources()
        {
            // 加载拼音哈希表
            GetPyHashs();
            // 初始化拼音编码字典
            GetPyCode();
            // 加载繁体字到简体字的映射表
            Q2b= LoadQ2B();
        }

        #endregion

        #region 读入文字表
        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 获取拼音编码表
        /// </summary>
        private static void GetPyCode()
        {
            // 通过程序集资源获取拼音编码表文件流
            using (Stream stream= RootAssembly.GetManifestResourceStream($"{Prefix}.PinyinCodes.txt"))
                // 检查流是否可用，如果可用则调用SetPyCode方法设置拼音编码表
                if (stream != null) SetPyCode(stream);
        }

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 设置拼音编码表
        /// </summary>
        private static void SetPyCode(Stream stream)
        {
            // 使用StreamReader读取流中的内容
            using (StreamReader reader= new StreamReader(stream))
                // 将读取的内容反序列化为字符串数组，并赋值给codes
                codes= JsonConvert.DeserializeObject<string[]>(reader.ReadToEnd());
        }

        #endregion

        #region 读入哈希表文件

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////      
        /// <summary>
        /// 获取拼音哈希数据
        /// </summary>
        /// <remarks>
        /// 该方法从资源文件中获取拼音哈希数据，并将其设置到程序中
        /// 它首先尝试获取ManifestResourceStream流，并在成功获取流后调用SetPyHashs方法
        /// </remarks>
        private static void GetPyHashs()
        {
            using (Stream stream1= RootAssembly.GetManifestResourceStream($"{Prefix}.PinyinHashs.txt"))
                if (stream1 != null) SetPyHashs(stream1);
        }

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 设置拼音哈希数据
        /// </summary>
        /// <param name="stream">包含拼音哈希数据的流</param>
        /// <remarks>
        /// 该方法通过流来设置拼音哈希数据
        /// 它将传入的流传递给StreamReader，并调用SetPyHashs方法来完成设置
        /// </remarks>
        private static void SetPyHashs(Stream stream)
        {
            using (StreamReader reader= new StreamReader(stream))
            {
                hashes= JsonConvert.DeserializeObject<short[][]>(reader.ReadToEnd());
                //SetPyCode(stream, reader);
            }
        }

        #endregion

        #region 加载全角到半角的映射
        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 加载全角到半角的映射。
        /// </summary>
        /// <returns>全角到半角的映射字典。</returns>
        public static Dictionary<string, string> LoadQ2B()
        {
            using Stream stream= RootAssembly.GetManifestResourceStream($"{Prefix}.q2b.dic")!;
            return ReadLines(stream)
                .Select(line=> line.Split('\t'))
                .ToDictionary(parts=> parts[0], parts=> parts[1]);
        }

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 从流中逐行读取数据。
        /// </summary>
        /// <param name="stream">要读取数据的流。</param>
        /// <returns>包含每一行数据的可枚举集合。</returns>
        internal static IEnumerable<string> ReadLines(Stream stream)
        {
            using StreamReader reader= new StreamReader(stream);
            while (!reader.EndOfStream)
            {
                yield return reader.ReadLine()!;
            }
        }
        #endregion

        #region 保存拼音字典及索引

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
        /// <summary>
        /// 保存数据到文件
        /// </summary>
        /// <remarks>
        /// 此方法将数据保存到两个不同的文件位置
        /// 首先，它调用WriteTextFileToLocation方法将数据保存到第一个位置
        /// 然后，调用WriteTextFileToLocation1方法将数据保存到第二个位置
        /// </remarks>
        public static void SaveToFile()
        {
            WriteTextFileToLocation();
            WriteTextFileToLocation1();
        }

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 将文本数据写入到指定位置的文件中。
        /// </summary>
        /// <remarks>
        /// 此方法使用 StreamWriter 将 JSON 格式的数据写入到名为 "PinyinHashs.txt" 的文件中。
        /// 这是为了保存 PyHash 类型的哈希数据，以便于后续的访问或使用。
        /// 使用 UTF-8 编码确保了文件的兼容性和可读性。
        /// </remarks>
        public static void WriteTextFileToLocation()
        {
            using (StreamWriter streamWriter= new StreamWriter("PinyinHashs.txt", false, Encoding.UTF8))
                streamWriter.Write(JsonConvert.SerializeObject(hashes));
        }

        // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////      
        /// <summary>
        /// 将拼音代码序列化为JSON字符串并写入指定文本文件。
        /// </summary>
        /// <remarks>
        /// 此方法使用JsonConvert.SerializeObject方法将PyCode.codes对象转换为JSON字符串，
        /// 然后使用StreamWriter将这个字符串写入到名为"PinyinCodes.txt"的文件中。
        /// 使用UTF8编码写入文件，且不会追加内容。
        /// </remarks>
        public static void WriteTextFileToLocation1()
        {
            using (StreamWriter streamWriter= new StreamWriter("PinyinCodes.txt", false, Encoding.UTF8))
                streamWriter.Write(JsonConvert.SerializeObject(codes));
        }

        #endregion
    }
}

